package ink.xiaobaibai.controller.onePay;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ink.xiaobaibai.annotation.InsidePublicResources;
import ink.xiaobaibai.autoConfig.roleResources.ResourcesRoleMapping;
import ink.xiaobaibai.common.MyRole;
import ink.xiaobaibai.common.PageInfo;
import ink.xiaobaibai.entity.*;
import ink.xiaobaibai.enumOxy.DeviceStatus;
import ink.xiaobaibai.multipleClick.ForbidMultipleClick;
import ink.xiaobaibai.response.ResponseFormat;
import ink.xiaobaibai.service.*;
import ink.xiaobaibai.serviceOxy.onePay.IDeviceOzoneControlService;
import ink.xiaobaibai.serviceOxy.onePay.IGeoDeviceService;
import ink.xiaobaibai.units.MySecurity;
import ink.xiaobaibai.valited.DeviceStatusValid;
import ink.xiaobaibai.valited.UpdateGroup;
import ink.xiaobaibai.vo.OrderItemInfoVo;
import ink.xiaobaibai.vo.UserByDeviceVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * @description: 臭氧机控制层
 * @author: 小白白
 * @create: 2021-05-23
 **/

@RestController
@RequestMapping("/onePay/ozoneDevice")
@CrossOrigin
@Api(tags = "臭氧机控制接口")
@InsidePublicResources
public class OzoneDeviceController {

    @Autowired
    private IOzoneDeviceService ozoneDeviceService;

    @Autowired
    private IOxygenDeviceService oxygenDeviceService;

    @Autowired
    private IGeoDeviceService geoDeviceService;

    @Autowired
    private IClientOrderService clientOrderService;

    @Autowired
    private IDeviceOzoneControlService deviceControlService;

    @Autowired
    private IOzonePriceService priceService;

    @Autowired
    private IAdminUserService adminUserService;

    /**
     * 获取臭氧机集合
     * 分页|识别码|个人|部门|故障|运行|空闲
     */
    @GetMapping("/list")
    @ApiOperation("获取臭氧机集合|查询条件: 分页,识别码(可选),个人(可选),部门(可选),故障机器(可选),空闲机器(可选),运行机器(可选),个人和部门不可同时存在,识别码不可和其他参数同时存在")
    public ResponseFormat getOzoneDeviceList(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                             @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize,
                                             @RequestParam(value = "code", required = false) String code,
                                             @RequestParam(value = "adminUserId", required = false) Integer adminUserId,
                                             @RequestParam(value = "depId", required = false) Integer depId,
                                             @RequestParam(value = "provinceCity", required = false) String provinceCity,
                                             @RequestParam(value = "status", required = false) @DeviceStatusValid String status) {
        String role = MySecurity.getRole();
        Set<String> roles = MySecurity.getRoles();
        Integer userId = MySecurity.getUserId();
        if (!roles.contains(MyRole.POWER_ONE)) {
            if (role.equals(MyRole.DISTRIBUTOR)) {
                //业务员
                depId = null;
                adminUserId = userId;
            } else if (role.equals(MyRole.AGENT)) {
                //经理
                //机器码校验
                if (code != null) {
                    //不能查看其他部门的机器
                    QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
                    q1.eq("device_code", code);
                    OzoneDevice ozone = this.ozoneDeviceService.getOne(q1);
                    if (ozone == null) {
                        return ResponseFormat.fail("当前机器不存在");
                    }
                    if (!this.adminUserService.identicalDep(ozone.getAdminUserId(), userId)) {
                        return ResponseFormat.fail("不可查看其他部门机器");
                    }
                    if (ozone.getStatus().equals(DeviceStatus.INUSE.getStatus()) && ozone.getWorkStopTime().getTime() < System.currentTimeMillis()) {
                        ozone.setStatus(DeviceStatus.FREE.getStatus());
                    }
                    return ResponseFormat.success(new PageInfo<>(Collections.singletonList(ozone), 1, 1));
                }
                //部门校验
                if (depId != null && StringUtils.equals(depId.toString(), this.adminUserService.getDepId(userId).toString())) {
                    return ResponseFormat.fail("不可查看其他部门机器");
                }
                //用户校验
                if (adminUserId != null && !this.adminUserService.identicalDep(adminUserId, userId)) {
                    return ResponseFormat.fail("不可查看其他部门人员机器");
                }
            }
        }
        if (code != null) {
            //不能查看其他部门的机器
            QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
            q1.eq("device_code", code);
            OzoneDevice ozone = this.ozoneDeviceService.getOne(q1);
            if (ozone == null) {
                return ResponseFormat.fail("当前机器不存在");
            }
            if (ozone.getStatus().equals(DeviceStatus.INUSE.getStatus()) && ozone.getWorkStopTime().getTime() < System.currentTimeMillis()) {
                ozone.setStatus(DeviceStatus.FREE.getStatus());
            }
            return ResponseFormat.success(new PageInfo<>(Collections.singletonList(ozone), 1, 1));
        }
        PageInfo<OzoneDevice> pageInfo = this.ozoneDeviceService.getListByAdmin(pageNum, pageSize, adminUserId, depId, provinceCity, status);
        for (OzoneDevice ozoneDevice : pageInfo.getData()) {
            if (ozoneDevice.getStatus().equals(DeviceStatus.INUSE.getStatus()) && ozoneDevice.getWorkStopTime().getTime() < System.currentTimeMillis()) {
                ozoneDevice.setStatus(DeviceStatus.FREE.getStatus());
            }
        }
        return ResponseFormat.success(pageInfo);
    }

    /**
     * 单臭氧机详细信息 获取当前臭氧机的详细信息: 负责人名称,负责部门名称,单机营业额
     */
    @GetMapping("/item/{id}")
    @ApiOperation("单臭氧机信息(只有机器信息)")
    public ResponseFormat<OrderItemInfoVo> getOzoneItem(@PathVariable("id") Integer id) {
        //机器信息
        OzoneDevice ozoneDevice = this.ozoneDeviceService.getById(id);
        if (ozoneDevice.getStatus().equals(DeviceStatus.INUSE.getStatus()) && ozoneDevice.getWorkStopTime().getTime() < System.currentTimeMillis()) {
            ozoneDevice.setStatus(DeviceStatus.FREE.getStatus());
        }
        return ResponseFormat.success(new OrderItemInfoVo(ozoneDevice, null, null, null));
    }

    @GetMapping("/item/detailed/{id}")
    @ApiOperation("臭氧机详细信息(机器信息+价格信息+负责人信息+总营业额)")
    public ResponseFormat<OrderItemInfoVo> getOzoneItemDetail(@PathVariable("id") Integer id) {
        //机器信息
        OzoneDevice ozoneDevice = this.ozoneDeviceService.getById(id);
        if (ozoneDevice.getStatus().equals(DeviceStatus.INUSE.getStatus()) && ozoneDevice.getWorkStopTime().getTime() < System.currentTimeMillis()) {
            ozoneDevice.setStatus(DeviceStatus.FREE.getStatus());
        }
        //价格信息
        OzonePrice price = this.priceService.getById(ozoneDevice.getPriceId());
        //负责人信息+负责人部门
        UserByDeviceVo userByDeviceId = this.ozoneDeviceService.getUserInfoByUserId(ozoneDevice.getAdminUserId());
        //此机器至今总营业额
        BigDecimal sumOrderAmount = this.clientOrderService.sumOrderAmount(id);
        return ResponseFormat.success(new OrderItemInfoVo(ozoneDevice, userByDeviceId, sumOrderAmount, price));
    }

    /**
     * 获取一臭氧机的订单 和上方单体臭氧机信息配合使用
     */
    @GetMapping("/item/order/{id}")
    @ApiOperation("获取一臭氧机的订单")
    public ResponseFormat<PageInfo<ClientOrder>> getItemOrder(@RequestParam("pageNum") Integer pageNum,
                                                              @RequestParam("pageSize") Integer pageSize,
                                                              @PathVariable("id") Integer deviceId) {
        QueryWrapper<ClientOrder> q1 = new QueryWrapper<>();
        q1.eq("device_id", deviceId);
        int count = this.clientOrderService.count(q1);
        List<ClientOrder> list = this.clientOrderService.getOrderListByDeviceId(deviceId, pageNum, pageSize);
        return ResponseFormat.success(new PageInfo<>(list, count, pageSize));
    }

    /**
     * 添加臭氧机
     */
    @PostMapping("/add")
    @ApiOperation("添加臭氧机")
    @ResourcesRoleMapping(resourceName = "增加定点臭氧机", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat addOzoneDevice(@RequestBody @Validated OzoneDevice ozoneDevice) {
        ozoneDevice.setId(null);
        ResponseFormat state = this.validOzone(ozoneDevice);
        if (state.getCode() == 1) {
            return state;
        }
        //默认空闲状态
        Integer userId = MySecurity.getUserId();
        if (ozoneDevice.getAdminUserId() == null) {
            ozoneDevice.setAdminUserId(userId);
            ozoneDevice.setDepId(this.adminUserService.getDepId(userId));
        } else {
            if (!this.adminUserService.existsUser(ozoneDevice.getAdminUserId())) {
                return ResponseFormat.fail("绑定用户不存在");
            }
            ozoneDevice.setDepId(this.adminUserService.getDepId(ozoneDevice.getAdminUserId()));
        }
        ozoneDevice.setStatus(DeviceStatus.FREE.getStatus());
        this.ozoneDeviceService.save(ozoneDevice);
        this.geoDeviceService.addDevice(ozoneDevice);
        return ResponseFormat.success();
    }

    /**
     * 修改臭氧机(整体数据) 无状态
     */
    @PutMapping("/update")
    @ApiOperation("修改臭氧机(整体数据) 不可传入状态")
    @ResourcesRoleMapping(resourceName = "修改定点臭氧机", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat updateOzoneDevice(@RequestBody @Validated(value = UpdateGroup.class) OzoneDevice ozoneDevice) {
        if (ozoneDevice.getId() == null) {
            return ResponseFormat.fail("id不可为空");
        }
        ResponseFormat state = this.validOzone(ozoneDevice);
        if (state.getCode() == 1) {
            return state;
        }
        if (ozoneDevice.getAdminUserId() != null) {
            if (!this.adminUserService.existsUser(ozoneDevice.getAdminUserId())) {
                return ResponseFormat.fail("绑定用户不存在");
            }
            ozoneDevice.setDepId(this.adminUserService.getDepId(ozoneDevice.getAdminUserId()));
        }
        this.ozoneDeviceService.updateById(ozoneDevice);
        this.geoDeviceService.updateDevice(ozoneDevice);
        return ResponseFormat.success();
    }

    /**
     * 修改臭氧机状态
     * 只有启动和停止
     */
    @PutMapping("/update-status")
    @ApiOperation("修改臭氧机状态(单状态)|只有启动和停止|运行状态需要设置秒数")
    @ForbidMultipleClick(key = "#deviceId", durationSecondsTime = 3)
    @ResourcesRoleMapping(resourceName = "修改定点臭氧机状态", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat updateOzoneDeviceStatus(@RequestParam("deviceId") Integer deviceId,
                                                  @RequestParam("status") @DeviceStatusValid String status,
                                                  @RequestParam(value = "seconds", required = false) Integer seconds) {
        if (!(status.equals(DeviceStatus.FREE.getStatus()) || status.equals(DeviceStatus.INUSE.getStatus()))) {
            return ResponseFormat.fail("当前接口只能设置空闲(停止)或运行状态");
        }
        if (status.equals(DeviceStatus.INUSE.getStatus()) && seconds == null) {
            return ResponseFormat.fail("启动时请携带秒数");
        }
        if (seconds != null && seconds <= 0) {
            return ResponseFormat.fail("请输入正确的秒数");
        }
        QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
        q1.select("status", "work_stop_time");
        q1.eq("id", deviceId);
        OzoneDevice ozoneDevice = this.ozoneDeviceService.getOne(q1);
        if (status.equals(ozoneDevice.getStatus())) {
            return ResponseFormat.fail("当前状态已经是" + status + "了");
        }
        if (status.equals(DeviceStatus.INUSE.getStatus()) && ozoneDevice.getWorkStopTime().getTime() > System.currentTimeMillis()) {
            return ResponseFormat.fail("只有空闲状态下,才可以启动");
        }

        DeviceStatus deviceStatus = DeviceStatus.valueOf(status.toUpperCase());
        switch (deviceStatus) {
            /**
             * deviceControlService内部会修改状态
             */
            case INUSE:
                this.deviceControlService.openDeviceByAdmin(deviceId, seconds);
                break;
            case FREE:
                this.deviceControlService.closeDeviceByAdmin(deviceId, DeviceStatus.FREE);
                break;
            default:
                break;
        }
        return ResponseFormat.success();
    }

    /**
     * 将臭氧机变成停运
     */
    @PutMapping("/stopDevice")
    @ApiOperation("将臭氧机停运")
    @ForbidMultipleClick(key = "#deviceId", durationSecondsTime = 3)
    @ResourcesRoleMapping(resourceName = "将定点臭氧机停运", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat stopDevice(@RequestParam("deviceId") Integer deviceId) {
        QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
        q1.select("status");
        q1.eq("id", deviceId);
        OzoneDevice ozoneDevice = this.ozoneDeviceService.getOne(q1);
        if (ozoneDevice.getStatus().equals(DeviceStatus.STOP.getStatus())) {
            return ResponseFormat.fail("当前机器已停运");
        }
        //将臭氧机停运
        this.deviceControlService.closeDeviceByAdmin(deviceId, DeviceStatus.STOP);
        return ResponseFormat.success();
    }

    /**
     * 将臭氧机从停运或者故障状态转为正常状态,即空闲状态
     */
    @PutMapping("/okDevice")
    @ApiOperation("将臭氧机从[故障/停运]变为正常状态")
    @ForbidMultipleClick(key = "#deviceId", durationSecondsTime = 3)
    @ResourcesRoleMapping(resourceName = "变成正常状态", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat okDevice(@RequestParam("deviceId") Integer deviceId) {
        return this.okFaultOrStop(deviceId);
    }

    /**
     * 删除臭氧机(运行状态不可以删除)
     */
    @DeleteMapping("/delete/{id}")
    @ApiOperation("删除臭氧机|运行状态不可删除")
    @ResourcesRoleMapping(resourceName = "删除臭氧机", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat deleteOzoneDevice(@PathVariable("id") Integer deviceId) {
        QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
        q1.select("id", "status", "work_stop_time");
        q1.eq("id", deviceId);
        OzoneDevice ozoneDevice = this.ozoneDeviceService.getOne(q1);
        if (ozoneDevice == null) {
            return ResponseFormat.fail("当前臭氧机不存在");
        }
        if (ozoneDevice.getWorkStopTime().getTime() > System.currentTimeMillis()) {
            return ResponseFormat.fail("正在使用中,不可删除");
        }
        this.ozoneDeviceService.removeById(deviceId);
        this.geoDeviceService.deleteDevice(ozoneDevice);
        return ResponseFormat.success();
    }

    @GetMapping("/price/list")
    @ApiOperation("价格时间段列表")
    public ResponseFormat priceList(@RequestParam(value = "pageNum", defaultValue = "1", required = false) Integer pageNum,
                                    @RequestParam(value = "pageSize", defaultValue = "20", required = false) Integer pageSize) {
        Page<OzonePrice> page = this.priceService.page(new Page<>(pageNum, pageSize));
        return ResponseFormat.success(page);
    }

    @DeleteMapping("/price/delete/{id}")
    @ApiOperation("删除当前价格时间段")
    @ResourcesRoleMapping(resourceName = "删除当前价格时间段", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat deletePriceItem(@PathVariable("id") Integer id) {
        QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
        q1.eq("price_id", id);
        q1.last("limit 1");
        if (this.ozoneDeviceService.count(q1) != 0) {
            return ResponseFormat.fail("尚未与所有机器解除关联,不可删除");
        }
        this.priceService.removeById(id);
        return ResponseFormat.success();
    }

    @PostMapping("/price/add")
    @ApiOperation("增加价格时间段")
    @ResourcesRoleMapping(resourceName = "增加价格时间段", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat addPrice(@RequestBody @Validated OzonePrice ozonePrice) {
        this.priceService.save(ozonePrice);
        return ResponseFormat.success();
    }

    @GetMapping("/priceByDeiceId/{id}")
    @ApiOperation("根据机器id获取价格时间段")
    @ResourcesRoleMapping(resourceName = "根据机器id获取价格时间段", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat getPriceByDeviceId(@PathVariable("id") Integer deviceId) {
        QueryWrapper<OzoneDevice> q2 = new QueryWrapper<>();
        q2.select("price_id");
        q2.eq("id", deviceId);
        Integer priceId = this.ozoneDeviceService.getOne(q2).getPriceId();
        return ResponseFormat.success(this.priceService.getById(priceId));
    }

    @PutMapping("/price/updateByDevice")
    @ApiOperation("为一台机器修改价格时间段")
    @ResourcesRoleMapping(resourceName = "为一台机器修改价格时间段", includeRoleNames = {MyRole.ADMIN, MyRole.POWER_ONE})
    public ResponseFormat updatePrice(@RequestParam("deviceId") Integer deviceId,
                                      @RequestParam("priceId") Integer priceId) {
        QueryWrapper<OzonePrice> q1 = new QueryWrapper<>();
        q1.eq("id", priceId);
        if (this.priceService.count(q1) == 0) {
            return ResponseFormat.fail("当前时间段不存在");
        }
        UpdateWrapper<OzoneDevice> u1 = new UpdateWrapper<>();
        u1.set("price_id", priceId);
        u1.eq("id", deviceId);
        this.ozoneDeviceService.update(u1);
        return ResponseFormat.success();
    }

    /**
     * 臭氧机修改校验
     */
    private ResponseFormat validOzone(OzoneDevice ozoneDevice) {
        //价格时间段是否存在
        Integer priceId = ozoneDevice.getPriceId();
        QueryWrapper<OzonePrice> q0 = new QueryWrapper<>();
        q0.eq("id", priceId);
        q0.last("limit 1");
        if (this.priceService.count(q0) == 0) {
            return ResponseFormat.fail("对应价格时间段不存在");
        }
        //识别码是否重复
        String deviceCode = ozoneDevice.getDeviceCode();
        QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
        q1.select("id", "device_code");
        q1.eq("device_code", deviceCode);
        OzoneDevice dbOzone = this.ozoneDeviceService.getOne(q1);
        if (ozoneDevice.getId() == null && dbOzone != null) {
            return ResponseFormat.fail("识别码重复");
        }
        if (ozoneDevice.getId() != null && !dbOzone.getId().equals(ozoneDevice.getId())) {
            return ResponseFormat.fail("识别码重复");
        }
        //关联的制氧机是否存在
        Integer oxygenId = ozoneDevice.getOxygenId();
        QueryWrapper<OxygenDevice> q2 = new QueryWrapper<>();
        q2.eq("id", oxygenId);
        if (this.oxygenDeviceService.count(q2) == 0) {
            return ResponseFormat.fail("关联的制氧机不存在");
        }
        if (ozoneDevice.getId() != null) {
            //修改的时候:对应的负责人是否存在
            if (ozoneDevice.getAdminUserId() != null) {
                Integer adminUserId = ozoneDevice.getAdminUserId();
                QueryWrapper<AdminUser> q3 = new QueryWrapper<>();
                q3.eq("id", adminUserId);
                q3.last("limit 1");
                if (this.adminUserService.count(q3) == 0) {
                    return ResponseFormat.fail("对应负责人不存在");
                }
            }
        }
        return ResponseFormat.success();
    }

    public ResponseFormat okFaultOrStop(Integer deviceId) {
        QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
        q1.select("status", "oxygen_id");
        q1.eq("id", deviceId);
        OzoneDevice ozoneDevice = this.ozoneDeviceService.getOne(q1);
        String status = ozoneDevice.getStatus();
        if (status.equals(DeviceStatus.INUSE.getStatus()) || status.equals(DeviceStatus.FREE.getStatus())) {
            return ResponseFormat.fail("当前机器已是正常状态");
        }
        /**
         * 如果对应氧气机是故障状态或者停运状态,那么需要给出提示
         */
        QueryWrapper<OxygenDevice> q2 = new QueryWrapper<>();
        q2.select("status");
        q2.eq("id", ozoneDevice.getOxygenId());
        OxygenDevice oxygenDevice = this.oxygenDeviceService.getOne(q2);
        if (oxygenDevice.getStatus().equals(DeviceStatus.STOP.getStatus()) || oxygenDevice.getStatus().equals(DeviceStatus.FAULT.getStatus())) {
            return ResponseFormat.fail("对应氧气机状态为:" + oxygenDevice.getStatus() + ",不可将臭氧机修改为正常状态");
        }
        //变为正常状态
        UpdateWrapper<OzoneDevice> u1 = new UpdateWrapper<>();
        u1.set("status", DeviceStatus.FREE.getStatus());
        u1.eq("id", deviceId);
        this.ozoneDeviceService.update(u1);
        return ResponseFormat.success();
    }

}
